package qatool

import cn.qs.qatool.StringUtils
import grails.codegen.model.Model
import grails.dev.commands.*
import org.grails.io.support.FileSystemResource

import java.lang.reflect.Field

class GenVueCommand implements GrailsApplicationCommand {
    def labelsTmpl ="""export default {
    'zh-CN': {
        \${keyVals}
    },
    'en-US': {
        \${keyVals}
    }
};"""

    def indexVue = """
<style lang="less">
    @import '\${commonLessPath}';
    @import '\${tableLessPath}';
</style>

<template>
    <div>
        <Row class="margin-top-10">
            <Col span="24" class="padding-left-10">
                <Card>
                    <Row slot="title" type="flex" justify="space-between" align="middle">
                        <H3>{{\\\\\\\$t("domain_\${propertyName}")}}</H3>
                        <Button type="primary" @click="new\${name}">{{\\\\\\\$t("new")}}</Button>
                    </Row>
                    <can-edit-table refs="table${name}" v-model="list\${name}" :hover-show="true" :edit-incell="true"
                                    @on-cell-change="handleCellChange"
                                    @on-change="handleChange"
                                    :columns-list="columns"></can-edit-table>
                </Card>
            </Col>
        </Row>
    </div>
</template>

<script>
    import canEditTable from '\${editableTableCmpPath}';

    export default {
        name: '\${name}-index',
        components: {
            canEditTable
        },
        data() {
            return {
                columns: [
        \${columns}
        {
            title: this.\\\\\\\$t("operation"),
            align: 'center',
            width: '200px',
            key: 'handle',
//            fixed: 'right',
            handle: ['edit', 'delete']
        }
    ],
                list\${name}: []
            };
        },
        methods: {
            new\${name}() {
                let \${name} = {}
                \${name}.isNew = true
                this.list\${name}.unshift(\${name})

            },
            handleNetConnect(state) {
                this.breakConnect = state;
            },
            handleLowSpeed(state) {
                this.lowNetSpeed = state;
            },
            getCurrentData() {
                this.showCurrentTableData = true;
            },
            handleDel(val, index) {
                this.\\\\\\\$Message.success('删除了第' + (index + 1) + '行数据');
            },
            handleCellChange(val, index, key) {
                debugger
                fetch(`\${url}`, {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify(val[index])
                }).then(r => r.json())
                    .then(json => {
                        this.\\\\\\\$Message.success('修改了第 ' + (index + 1) + ' 行列名为 ' + key + ' 的数据');
                    })
                    .catch(ex =>
                        this.\\\\\\\$Message.error('修改第 ' + (index + 1) + ' 行列名为 ' + key + ' 的数据失败，详情：' + ex))

            },
            handleChange(val, index) {
                fetch(`\${url}`, {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify(val[index])
                }).then(r => r.json())
                    .then(json => {
                        this.\\\\\\\$Message.success('修改了第 ' + (index + 1) + ' 行的数据');
                    })
                    .catch(ex =>
                        this.\\\\\\\$Message.error('修改第 ' + (index + 1) + ' 行的数据失败，详情：' + ex))
            }
        },
        created() {
            fetch(`\${url}`)
                .then(response => response.json())
                .then(json => {
                    if(json.message){
                        this.\\\\\\\$Message.error(json.message)
                    }else {
                        this.list\${name} = json
                    }
                })
        }
    };
</script>

"""
    def labels = [:]

    private File serverDir,clientDir,templateDir
    boolean handle() {
        def commands = this.executionContext.commandLine.rawArguments
        def domainClassName = commands[1]
        def classNames = []

        def baseDir = executionContext.baseDir
        serverDir = baseDir.getAbsoluteFile().getParentFile()
        clientDir = new File(baseDir.getAbsoluteFile().getParentFile().getParentFile(),"client")
        templateDir = new File(serverDir,"src/main/templates/scaffolding")
        File targetDir = new File(clientDir, "src/views")
        System.out.println("---->genVueCode")
        if(domainClassName.trim().equals('all')) {
            classNames = resources("file:grails-app/domain/**/*.groovy").collect {
                it.getPath().replaceAll(".*domain/","").replaceAll(".groovy","").replaceAll(File.separator,".")
            }
        } else {
            classNames.add(domainClassName)
        }
        classNames.each {
            String className = it
            def model = model(className)
            labels.put("domain_${model.propertyName}",model.simpleName)
            System.out.println("---->genVueCode")
            genVueCode(targetDir,model,className)
        }
        System.out.println("---->genVueRouter")
        genVueRouter(classNames)
        System.out.println("---->genLabels")
        genLabels()
        return true
    }

    def genLabels() {
        String keyVals = ""
        labels.each {
            keyVals += "        ${it.key}: '${it.value}',"
        }
        if(keyVals.length()>1){
            keyVals = keyVals.substring(0,keyVals.length()-1)  //remove trailing ','
        }
        String template = StringUtils.bind(labelsTmpl, [keyVals:keyVals])
        templateRenderer.render(template,new File(clientDir,"src/locale/gen_local.js"))
    }

    private void genVueCode(File targetDir, def model, String className){
        genVueComp(targetDir,model,className)
        genStore(targetDir,model,className)

    }

    private void genVueComp(def targetDir,Model model,String className){
        def modelMap = [:]
        modelMap.model = model
        def fields = Class.forName(model.fullName).declaredFields
        File targetFile = new File(targetDir,"${model.packagePath}/${model.propertyName}/index.vue")

        def packageLevel = ""
        def length = className.split('\\.').length -1
        (length).times {
            packageLevel += "../"
        }
        def commonLessPath = packageLevel +"../../styles/common.less"
        def tableLessPath = packageLevel +"../tables/components/table.less"
        System.out.println("----> def columns = {")
        def columns = """{
                        title: this.\\\$t("SN"),
                        type: 'index',
                        align: 'center',
                        width: '100px'
                      },"""
        System.out.println("----> fields.each {")
        fields.each {
            if(it.modifiers == 2 && !it.name.contains("org_grails")){
                labels.put("field_${it.name}",it.name)
                columns += """{
                                title: this.\\\$t("field_${it.name}"),
                                align: 'center',
                                key: '${it.name}',
                                editable: true},"""
            }
        }
        System.out.println("----> def editableTableCmpPath")
        def editableTableCmpPath = packageLevel + "../tables/components/canEditTable.vue"
        def map = [name:model.simpleName,
                   propertyName:model.propertyName,
                   commonLessPath:commonLessPath,
                   columns:columns,
                   url: "http://localhost:8080/${model.propertyName}",
                   editableTableCmpPath: editableTableCmpPath,
                   tableLessPath:tableLessPath]
        String template = StringUtils.bind(indexVue, map)
        templateRenderer.render(template,targetFile)

    }


    def appRouterTmpl = """
import Main from '@/views/Main.vue';

// 作为Main组件的子页面展示并且在左侧菜单显示的路由写在appRouter里
export const appRouter = [
    \${items}
];\n"""
    def routerItemTmpl = """{
        path: '/\${name}',
        icon: '\${name}',
        name: '\${name}',
        title: {i18n: 'domain_\${name}'},
        component: Main,
        children: [
            { path: '\${name}', title: {i18n: 'domain_\${name}'}, name: '\${name}_index', component: () => import('@/views/\${path}/index.vue') }
        ]
    }, """
    private void genVueRouter(classNames){

        def items = ""
        classNames.each{
            String className = it
            def model = model(className)
            items += StringUtils.bind(routerItemTmpl,[name:model.propertyName,path:model.packagePath+File.separator+model.propertyName])
        }
        items = items.substring(0,items.length()-2)
        def appRouter = StringUtils.bind(appRouterTmpl,[items:items])

        File targetFile = new File(clientDir,"src/router/appRouter.js")
        templateRenderer.render(appRouter,targetFile)

    }


    private void genStore(def targetDir,def model,String className){

    }

}

